package com.mls.fivedistrict.mq;

import com.baidu.aip.ocr.AipOcr;
import com.google.gson.Gson;
import com.mls.fivedistrict.entity.response.BDOCRBackResponse;
import com.mls.fivedistrict.entity.response.BDOCRIDResponse;
import com.mls.fivedistrict.entity.response.OCRIDResponse;
import com.mls.fivedistrict.enums.*;
import com.mls.fivedistrict.exception.CustomerException;
import com.mls.fivedistrict.pojo.*;
import com.mls.fivedistrict.server.*;
import com.mls.fivedistrict.server.impl.UserTaskService;
import com.mls.fivedistrict.util.Base64Img;
import com.mls.fivedistrict.util.JsonUtils;
import com.mls.fivedistrict.util.TimeUtils;
import com.mls.fivedistrict.util.http.BDOcrClient;
import com.mls.fivedistrict.util.http.HttpUtil;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 实名认证的消费者
 * Created by chenxiuxiang on 2018/5/31.
 */
@Slf4j
public class AuthenticationCustomer implements ChannelAwareMessageListener {
    @Autowired
    UserAuthService userAuthService;
    @Autowired
    TaskService taskService;
    @Autowired
    UserService userService;

    @Autowired
    UserAuthRewardRecordService userAuthRewardRecordService;

    @Autowired
    TaskRewardService taskRewardService;

    @Autowired
    UserRoleService userRoleService;

    @Autowired
    UserTaskService userTaskService;

    @Autowired
    CalculateService calculateService;
    @Autowired
    PropertyService propertyService;

    @Autowired
    RecordService recordService;

    @Transactional
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        try {
            String json = new String(message.getBody(), "utf-8");
            UserAuth userAuth = JsonUtils.jsonToPojo(json, UserAuth.class);
            //1.调用API接口验证
            bdOcrVerify(userAuth);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }


    }

    private void bdOcrVerify(UserAuth userAuth) {
        UserAuth userAuthDetail = userAuthService.getUserAuth(userAuth.getId());
        if (!StringUtils.isEmpty(userAuthDetail.getStatus())) {
            //代表已经审核过
            log.info("已经审核过{}", userAuthDetail.getStatus());
            return;
        }
        AipOcr client = BDOcrClient.getInstance();
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("detect_direction", "true");
        options.put("detect_risk", "true");
        //正面识别
        String image = userAuth.getPositiveImage() + "?x-oss-process=image/resize,m_mfit,h_800,w_800";
        byte[] imageFromNetByUrl = Base64Img.getImageFromNetByUrl(image);
        JSONObject res = client.idcard(imageFromNetByUrl, "front", options);
        String s = new Gson().toJson(res);
        log.info("正面：{}", s);
        BDOCRIDResponse bdocridResponse = new Gson().fromJson(s, BDOCRIDResponse.class);
        if (bdocridResponse == null || bdocridResponse.getMap().getError_code() != 0) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("图片地址错误正面未识别");
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }
        //反面识别
        String backImage = userAuth.getReverseImage() + "?x-oss-process=image/resize,m_mfit,h_800,w_800";
        byte[] imageFromNetByUrlBack = Base64Img.getImageFromNetByUrl(backImage);
        JSONObject backRes = client.idcard(imageFromNetByUrlBack, "back", options);
        log.info("反面：{}", new Gson().toJson(backRes));
        BDOCRBackResponse bdocrBackResponse = new Gson().fromJson(new Gson().toJson(backRes), BDOCRBackResponse.class);
        if (bdocrBackResponse == null || bdocrBackResponse.getMap().getError_code() != 0) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("图片地址错误反面未识别");
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }
        //判断是否是正常身份证
        String image_status = bdocridResponse.getMap().getImage_status();
        String risk_type = bdocridResponse.getMap().getRisk_type();
        if (!image_status.equals("normal") || !risk_type.equals("normal")) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("不是正常身份证:" + image_status + ",risk_type:" + risk_type);
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }
        //判断是否是正常身份证
        String image_status_back = bdocrBackResponse.getMap().getImage_status();
        String risk_type_back = bdocridResponse.getMap().getRisk_type();
        if (!image_status_back.equals("normal") || !risk_type_back.equals("normal")) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("不是正常身份证:" + image_status_back + ",risk_type:" + risk_type_back);
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }
        //判断是否为空的
        if (bdocrBackResponse.getMap().getWords_result().getMap().get签发机关() == null || bdocridResponse.getMap().getWords_result().getMap().get住址() == null ||
                bdocridResponse.getMap().getWords_result().getMap().get姓名() == null || bdocridResponse.getMap().getWords_result().getMap().get公民身份号码() == null || bdocrBackResponse.getMap().getWords_result().getMap().get失效日期() == null) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("签发机关或者住址为空姓名公民身份号码失效日期");
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }


        //判断姓名证件是否一致
        String realName = bdocridResponse.getMap().getWords_result().getMap().get姓名().getMap().getWords();
        String cardNo = bdocridResponse.getMap().getWords_result().getMap().get公民身份号码().getMap().getWords();
        if (!userAuth.getRealName().equals(realName) || !userAuth.getCradNo().toUpperCase().equals(cardNo.toUpperCase())) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("姓名证件不一致:" + realName + ",:" + cardNo);
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }
        //判断证件有效期
        String endDate = bdocrBackResponse.getMap().getWords_result().getMap().get失效日期().getMap().getWords();
        if (!endDate.equals("长期")) {
            if (StringUtils.isEmpty(endDate)) {
                UserAuth newUserAuth = new UserAuth();
                newUserAuth.setId(userAuth.getId());
                newUserAuth.setReason("身份证已失效:" + endDate);
                newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
                userAuthService.updateUserAuth(newUserAuth);
                return;
            }
            String y = endDate.substring(0, 4);
            String m = endDate.substring(4, 6);
            String d = endDate.substring(6, 8);
            long l = TimeUtils.string2Millis(y + "." + m + "." + d, TimeUtils.DOT_FORMAT);
            if (l < new Date().getTime()) {
                UserAuth newUserAuth = new UserAuth();
                newUserAuth.setId(userAuth.getId());
                newUserAuth.setReason("身份证已失效:" + endDate);
                newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
                userAuthService.updateUserAuth(newUserAuth);
                return;
            }
        }
        //判断地址

        String address = bdocrBackResponse.getMap().getWords_result().getMap().get签发机关().getMap().getWords();
        String fullAddress = bdocridResponse.getMap().getWords_result().getMap().get住址().getMap().getWords();
        String substring = address.substring(0, 2);
        if (!fullAddress.contains(substring)) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("地址不一致" + address + "," + fullAddress);
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }
        //校验完成
        UserAuthRewardRecord userAuthRewardRecord = new UserAuthRewardRecord();
        Task authTask = taskService.getTaskByCategory(TaskCategoryEnum.AUTHENTICATION.getValue());
        User userDetail = userService.getUserDetail(userAuth.getUserId());
        userAuthRewardRecord = completeOneSelfTask(authTask, userAuth.getUserId(), CalculateSourceEnum.Authentication.getValue(), RecordProductTypeEnum.AUTHENTICATION.getValue(), CalculateSourceEnum.Authentication.getDesc(), userAuthRewardRecord);
        if (userAuthRewardRecord == null) {
            UserAuth newUserAuth = new UserAuth();
            newUserAuth.setId(userAuth.getId());
            newUserAuth.setReason("发放奖励错误:任务已完成请勿重复提交");
            newUserAuth.setStatus(AuthStatusEnum.REJECT.getValue());
            userAuthService.updateUserAuth(newUserAuth);
            return;
        }
        User newUser = new User();
        newUser.setId(userAuth.getUserId());
        newUser.setRealname(userAuth.getRealName());
        int i = userService.editUser(newUser);
        if (i <= 0) {
            throw new CustomerException("更新用户信息失败");
        }
        UserAuth newUserAuth = new UserAuth();
        newUserAuth.setId(userAuth.getId());
        newUserAuth.setStatus(AuthStatusEnum.PASS.getValue());
        userAuthService.updateUserAuth(newUserAuth);
        if (userDetail.getInviterUserId() != null && userDetail.getInviterUserId() != 0) {
            userAuthRewardRecord = distributionRewards(authTask.getId(), userDetail.getId(), CalculateSourceEnum.Invite.getValue(), RecordProductTypeEnum.INVITE_FRIENDS.getValue(), CalculateSourceEnum.Invite.getDesc(), CalculateSourceEnum.SecondInvite.getValue(), RecordProductTypeEnum.SECOND_INVITE.getValue(), CalculateSourceEnum.SecondInvite.getDesc(), userAuthRewardRecord);
            userAuthRewardRecord.setUserId(userAuth.getUserId());
            userAuthRewardRecord.setUserAuthId(userAuth.getId());
            boolean flag = userAuthRewardRecordService.insert(userAuthRewardRecord);
            if (!flag) {
                throw new CustomerException("认证奖励记录创建失败");
            }

        }


    }


    /**
     * 实名认证完成发放奖励
     */
    public UserAuthRewardRecord distributionRewards(Long taskId, Long userId, String oneCalculateSource, String oneRecordSource, String oneReason, String twoCalculateSource, String twoRecordSource, String twoReason, UserAuthRewardRecord userAuthRewardRecord) {
        TaskReward taskReward = taskRewardService.getTaskRewardByTaskID(taskId);
        if (taskReward == null) {
            return null;
        }
        Long oneLevelRoleId = taskReward.getOneLevelRoleId();
        if (oneLevelRoleId != 0) {
            //1.判断一级角色为-1代表所有一级用户都可以获得 为0代表上级没有奖励
            User userDetail = userService.getUserDetail(userId);
            User inviteUser = userService.getUserDetail(userDetail.getInviterUserId());
            if (inviteUser == null) {
                return null;
            }
            if (oneLevelRoleId == -1) {
                userAuthRewardRecord.setOneLevelUserId(inviteUser.getId());
                rewardOneLevel(taskReward, inviteUser, oneCalculateSource, oneRecordSource, oneReason, userAuthRewardRecord);
            } else {
                //2.判断上级邀请人是否含有此角色
                List<UserRole> inviteUserRoleList = userRoleService.getUserRoleByUserId(inviteUser.getId());
                boolean hasRole = false;
                for (UserRole userRole : inviteUserRoleList) {
                    if (userRole.getRoleId().equals(oneLevelRoleId)) {
                        hasRole = true;
                    }
                }
                if (hasRole) {
                    userAuthRewardRecord.setOneLevelUserId(inviteUser.getId());
                    rewardOneLevel(taskReward, inviteUser, oneCalculateSource, oneRecordSource, oneReason, userAuthRewardRecord);
                }
            }

        }
        Long twoLevelRoleId = taskReward.getTwoLevelRoleId();
        if (twoLevelRoleId != 0) {
            //1.判断二级角色为-1代表所有一级用户都可以获得 为0代表没有奖励
            User userDetail = userService.getUserDetail(userId);
            User inviteUser = userService.getUserDetail(userDetail.getInviterUserId());
//            User inviteUser = userDetail.getInviterUser();
            User secondUser = userService.getUserDetail(inviteUser.getInviterUserId());
            if (twoLevelRoleId == -1 && secondUser != null) {
                userAuthRewardRecord.setSecondLevelUserId(secondUser.getId());
                rewardSecondLevel(taskReward, secondUser, twoCalculateSource, twoRecordSource, twoReason, userAuthRewardRecord);

            } else if (secondUser != null) {
                userAuthRewardRecord.setSecondLevelUserId(secondUser.getId());
                //2.判断上级邀请人是否含有此角色
                List<UserRole> inviteUserRoleList = userRoleService.getUserRoleByUserId(secondUser.getId());
                boolean hasRole = false;
                for (UserRole userRole : inviteUserRoleList) {
                    if (userRole.getRoleId().equals(twoLevelRoleId)) {
                        hasRole = true;
                    }
                }
                if (hasRole) {
                    rewardSecondLevel(taskReward, secondUser, twoCalculateSource, twoRecordSource, twoReason, userAuthRewardRecord);
                }
            }
        }
        return userAuthRewardRecord;
    }

    /**
     * 完成任务
     *
     * @param task
     * @param userId
     * @param calculateSource
     * @param recordSource
     */
    private UserAuthRewardRecord completeOneSelfTask(Task task, Long userId, String calculateSource, String recordSource, String reason, UserAuthRewardRecord userAuthRewardRecord) {
        //1.判断用户是否已经完成过
        UserTask userTask = userTaskService.getUserTask(task.getId(), userId);
        if (userTask != null) {
            return null;
        }
        int calculateValue = task.getValue().intValue();
        if (calculateValue > 0) {
            Calculate calculate = new Calculate();
            calculate.setUserId(userId);
            calculate.setValue(calculateValue);
            calculate.setType(task.getCalculateType());
            calculate.setSource(calculateSource);
            calculate.setChangeDescription(reason);
            Long calculateId = calculateService.insertCalculate(calculate);
            userAuthRewardRecord.setCalculateId(calculateId);
        }
        Long integralId = task.getIntegralId();
        if (integralId != null) {
            BigDecimal integralValue = task.getIntrgralValue();
            //添加积分
            Long propertyId = propertyService.addPropertyByIntegral(integralId, integralValue, userId);
            //添加记录
            Record record = new Record();
            record.setChangeReason(reason);
            record.setSource(recordSource);
            record.setUserId(userId);
            record.setIntergralId(integralId);
            record.setValue(integralValue);
            record.setStatus(RecordStatusEnum.ALREADYRECEIVE.getValue());
            record.setPropertyId(propertyId);
            recordService.insertRecordForId(record);
            userAuthRewardRecord.setIntegralId(integralId);
            userAuthRewardRecord.setIntegralValue(integralValue);
        }
        //
        UserTask addUserTask = new UserTask();
        addUserTask.setUserId(userId);
        addUserTask.setTaskId(task.getId());
        userTaskService.addUserTask(addUserTask);
        return userAuthRewardRecord;

    }


    /**
     * 发放一级奖励
     *
     * @param taskReward
     * @param inviteUser
     * @param userAuthRewardRecord
     */
    public void rewardOneLevel(TaskReward taskReward, User inviteUser, String calculateSource, String recordSource, String reason, UserAuthRewardRecord userAuthRewardRecord) {
        //为一级用户发放奖励
        long oneLevelIntegralId = taskReward.getOneLevelIntegralId();
        if (oneLevelIntegralId != 0) {

            //为一级用户添加积分
            BigDecimal oneLevelIntegralValue = taskReward.getOneLevelIntegralValue();
            Long propertyId = propertyService.addPropertyByIntegral(oneLevelIntegralId, oneLevelIntegralValue, inviteUser.getId());
            //添加记录
            Record record = new Record();
            record.setChangeReason(reason);
            record.setSource(recordSource);
            record.setUserId(inviteUser.getId());
            record.setIntergralId(oneLevelIntegralId);
            record.setValue(oneLevelIntegralValue);
            record.setStatus(RecordStatusEnum.ALREADYRECEIVE.getValue());
            record.setPropertyId(propertyId);
            recordService.insertRecordForId(record);
            userAuthRewardRecord.setOneLevelIntegralId(oneLevelIntegralId);
            userAuthRewardRecord.setOneLevelIntegralValue(oneLevelIntegralValue);
        }
        int oneLevelCalculateValue = taskReward.getOneLevelCalculateValue();
        if (oneLevelCalculateValue > 0) {
            //为一级用户添加算力
            Calculate calculate = new Calculate();
            calculate.setUserId(inviteUser.getId());
            calculate.setValue(oneLevelCalculateValue);
            calculate.setType(taskReward.getOneLevelCalculateType());
            calculate.setSource(calculateSource);
            calculate.setChangeDescription(reason);
            Long calculateId = calculateService.insertCalculate(calculate);
            userAuthRewardRecord.setOneLevelCalculateId(calculateId);

        }
    }

    /**
     * 发放二级奖励
     *
     * @param taskReward
     * @param secondUser
     */
    public void rewardSecondLevel(TaskReward taskReward, User secondUser, String calculateSource, String recordSource, String reason, UserAuthRewardRecord userAuthRewardRecord) {
        //为二级用户发放奖励
        long twoLevelIntegralId = taskReward.getTwoLevelIntegralId();
        if (twoLevelIntegralId != 0) {
            //为二级用户添加积分
            BigDecimal twoLevelIntegralValue = taskReward.getTwoLevelIntegralValue();
            Long propertyId = propertyService.addPropertyByIntegral(twoLevelIntegralId, twoLevelIntegralValue, secondUser.getId());
            //添加记录
            Record record = new Record();
            record.setChangeReason(reason);
            record.setSource(recordSource);
            record.setUserId(secondUser.getId());
            record.setIntergralId(twoLevelIntegralId);
            record.setValue(twoLevelIntegralValue);
            record.setStatus(RecordStatusEnum.ALREADYRECEIVE.getValue());
            record.setPropertyId(propertyId);
            recordService.insertRecordForId(record);
            userAuthRewardRecord.setTwoLevelIntegralId(twoLevelIntegralId);
            userAuthRewardRecord.setTwoLevelIntegralValue(twoLevelIntegralValue);
        }
        int twoLevelCalculateValue = taskReward.getTwoLevelCalculateValue();
        if (twoLevelCalculateValue > 0) {
            //为二级用户添加算力
            Calculate calculate = new Calculate();
            calculate.setUserId(secondUser.getId());
            calculate.setValue(twoLevelCalculateValue);
            calculate.setType(taskReward.getOneLevelCalculateType());
            calculate.setSource(calculateSource);
            calculate.setChangeDescription(reason);
            Long calculateId = calculateService.insertCalculate(calculate);
            userAuthRewardRecord.setTwoLevelCalculateId(calculateId);
        }
    }


}
